﻿Imports System.Runtime.InteropServices
Imports MirEvoSvr.Functions

Namespace NPC

    Friend Class MirNPCShopDef

        Dim ShopTableDefString As String

        Public Structure MirShopItemDef

            Dim BYTE_TYPE As ShopDefType

            Dim ID_ITEM As Long

            Dim ItemInfo As ItemBaseInfo

        End Structure

        Dim mNPC_ID As Long
        Dim lstShopDef As List(Of MirShopItemDef)
        Dim lstAcceptsItemTypes As List(Of ItemType)
        Dim lstRepairsItemTypes As List(Of ItemType)

        Dim mShopSellRate As Single = 0.8F

        Dim mShopTableName As String

        Dim objLock As New Object

        Public Sub New(NPC_ID As Long)

            lstShopDef = New List(Of MirShopItemDef)
            lstAcceptsItemTypes = New List(Of ItemType)
            lstRepairsItemTypes = New List(Of ItemType)

            mNPC_ID = NPC_ID
            mShopTableName = "TBL_SHOPITEMS_NPC" & NPC_ID

            ShopTableDefString = "ID_ITEM bigint NOT NULL, " & _
                                    "BOOL_DELETED bit NOT NULL"


        End Sub

        Public Function LoadFromFile(file As String) As Integer

            Dim count As Integer, failcount As Integer


            If System.IO.File.Exists(file) Then

                Dim stream As System.IO.StreamReader = FileIO.FileSystem.OpenTextFileReader(file)
                Dim line As String

                Do Until stream.EndOfStream

                    Try

                        line = stream.ReadLine()
                        TrimLineTabs(line)

                        If Left(line, 1) <> ";" And line.Length > 0 Then

                            Dim flag As String = ReadNextValue(line)

                            Select Case UCase(flag)

                                Case "ADDITEM"
                                    Dim item As MirShopItemDef
                                    Dim name As String = ReadNextValue(line)
                                    Dim sSql As String = "SELECT ID_ITEMBASE FROM TBL_ITEMBASE WHERE STR_NAME='" & name & "';"
                                    Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

                                    If Not row Is Nothing Then
                                        If row.Count > 0 Then
                                            item.BYTE_TYPE = ShopDefType.StackItem
                                            item.ID_ITEM = row("ID_ITEMBASE")
                                            item.ItemInfo = ItemBaseInfoFromItemBaseID(item.ID_ITEM)
                                            lstShopDef.Add(item)
                                            count += 1
                                        Else
                                            Throw New Exception("Error in AddItem, possibly unknown item name")
                                        End If
                                    Else
                                        Throw New Exception("Error in AddItem, possibly unknown item name")
                                    End If

                                Case "SETBUYS"

                                    Dim param As String = ReadNextValue(line)

                                    If UCase(param) = "ALL" Or param = "*" Then

                                        For Each itemtype As ItemType In System.Enum.GetValues(GetType(ItemType))
                                            lstAcceptsItemTypes.Add(itemtype)
                                        Next

                                    Else

                                        Try
                                            Dim itemtype As Protocol.ItemType = System.Enum.Parse(GetType(ItemType), param)
                                            lstAcceptsItemTypes.Add(itemtype)
                                        Catch

                                        End Try

                                    End If

                                Case "SETREPAIRS"

                                    Dim param As String = ReadNextValue(line)

                                    If UCase(param) = "ALL" Or param = "*" Then

                                        For Each itemtype As ItemType In System.Enum.GetValues(GetType(ItemType))
                                            lstRepairsItemTypes.Add(itemtype)
                                        Next

                                    Else

                                        Try
                                            Dim itemtype As Protocol.ItemType = System.Enum.Parse(GetType(ItemType), param)
                                            lstRepairsItemTypes.Add(itemtype)
                                        Catch

                                        End Try

                                    End If

                                Case "SETSHOPTABLE"
                                    LoadShopTableFromDB(ReadNextValue(line))



                                Case Else
                                    Throw New Exception

                            End Select

                        End If

                    Catch ex As Exception

                        Throw New Exception(ex.Message)
                        Output.AddLine("\B0\F3NP>\B8\F7 Error in " & Right(file, file - (InStrRev(file, "\") + 1)) & "! Near '" & line & "'\F0")
                        failcount += 1

                    End Try
                Loop

                Output.AddLine("\B0\F3NP>\B8\F0 Loaded " & count & " rows from ShopDef for NPC: " & mNPC_ID & "! (\F7" & failcount & " failed\F0)")
                Return failcount

            End If

        End Function

        Public Sub ShopLoadItems(ByRef Conn As Connection, info As Protocol.ShopLoadItemsInfo)

            SyncLock objLock

                Dim sSql As String = "SELECT TOP 1000 a.ID_ITEM FROM " & mShopTableName & " a JOIN TBL_ITEMS b ON a.ID_ITEM = b.ID_ITEM WHERE b.ID_ITEMBASE=" & info.ID_ITEMBASE & " AND a.BOOL_DELETED='False';"
                Dim arr_rows As ArrayList = DB.GameDB.ExecuteQuery(sSql)
                Dim start_i As Integer = ((info.INT_PAGE - 1) * 12)

                Dim pkt As Packet
                pkt.PacketType = GamePacketType.NPCShopItemsBeginUpdate
                pkt.PacketOpCode = PacketOpCode.Notify
                pkt.Username = Conn.Username

                Dim shop_info As ShopInfo
                shop_info.BOOL_GRIDLIST = True
                shop_info.ID_NPC = mNPC_ID

                Socket.SockServer.SendData(MakePacket(pkt, shop_info, Conn.Crypto), Conn)

                pkt.PacketType = GamePacketType.NPCShopItemsAdd

                For i As Integer = start_i To start_i + 11
                    If i < arr_rows.Count Then

                        Dim item As ItemInfo = ItemInfoFromItemID(arr_rows(i)("ID_ITEM"))

                        Dim item_info As Protocol.ShopItemInfo
                        item_info.Info = item
                        item_info.BYTE_DEFTYPE = Protocol.ShopDefType.GridItem
                        Socket.SockServer.SendData(MakePacket(pkt, item_info, Conn.Crypto), Conn)
                    End If
                Next

                pkt.PacketType = GamePacketType.NPCShopItemsEndUpdate
                Socket.SockServer.SendData(MakePacket(pkt, , Conn.Crypto), Conn)

            End SyncLock

        End Sub

        Public Sub SendShopInfo(conn As SocketServer.Connection)

            Dim pkt As Packet
            pkt.PacketType = GamePacketType.NPCShopItemsBeginUpdate
            pkt.PacketOpCode = EvoLib.Protocol.mProtocol.PacketOpCode.Notify
            pkt.Username = conn.Username

            Dim beginstruct As Protocol.ShopInfo
            beginstruct.ID_NPC = mNPC_ID
            beginstruct.BOOL_GRIDLIST = False


            Socket.SockServer.SendData(MakePacket(pkt, beginstruct, conn.Crypto), conn.Index)

            pkt.PacketType = GamePacketType.NPCShopItemsAdd

            Dim addstruct As ShopItemInfo

            SyncLock objLock

                For Each item As MirShopItemDef In lstShopDef

                    addstruct.BYTE_DEFTYPE = item.BYTE_TYPE
                    addstruct.Info.Base = item.ItemInfo

                    Socket.SockServer.SendData(MakePacket(pkt, addstruct, conn.Crypto), conn.Index)
                    System.Windows.Forms.Application.DoEvents()

                Next

            End SyncLock

            pkt.PacketType = GamePacketType.NPCShopItemsEndUpdate
            Socket.SockServer.SendData(MakePacket(pkt, , conn.Crypto), conn.Index)


        End Sub

        Private Sub LoadShopTableFromDB(tblname As String)

            mShopTableName = tblname

            DB.GameDB.CheckTable(tblname, ShopTableDefString)

            Dim sSql As String = "SELECT DISTINCT b.ID_ITEMBASE FROM " & tblname & " a JOIN TBL_ITEMS b ON a.ID_ITEM = b.ID_ITEM WHERE a.BOOL_DELETED='False' AND b.BYTE_LOCATION=" & ItemLocation.Shop & ";"
            Dim row As ArrayList = DB.GameDB.ExecuteQuery(sSql)

            If Not row Is Nothing Then
                If row.Count > 0 Then
                    For i As Integer = 0 To row.Count - 1
                        Dim baseinfo As ItemBaseInfo = ItemBaseInfoFromItemBaseID(CLng(row(i)("ID_ITEMBASE")))
                        Dim shopdef As MirShopItemDef
                        shopdef.BYTE_TYPE = EvoLib.Protocol.mProtocol.ShopDefType.GridItem
                        shopdef.ID_ITEM = baseinfo.INT_ID_ITEMBASE
                        shopdef.ItemInfo = baseinfo
                        lstShopDef.Add(shopdef)
                    Next
                End If
            End If

        End Sub

        Public Sub BuyItem(conn As Connection, info As ShopItemBuyInfo)

            SyncLock objLock

                Select Case info.BYTE_DEFTYPE

                    Case ShopDefType.StackItem
                        Dim base As ItemBaseInfo = ItemBaseInfoFromItemBaseID(info.ID)
                        Dim cost As Long = CLng(base.INT8_COST * info.INT_COUNT)

                        If HasGold(conn, cost) Then


                            Dim id As Long
                            If base.BOOL_STACKS Then
                                id = CreateNewItem(base.STR_NAME, conn.CharacterID, info.INT_COUNT, ItemLocation.Inventory)
                            Else
                                info.INT_COUNT = 1
                                id = CreateNewItem(base.STR_NAME, conn.CharacterID, , ItemLocation.Inventory)
                            End If
                            LoadNewItem(conn, id)

                            TakeGold(conn, cost)
                        Else

                            Packets.SendSystemMessage(conn, "Not enough gold for that item!")

                        End If

                    Case ShopDefType.GridItem

                        Dim sSql As String = "SELECT BYTE_LOCATION FROM TBL_ITEMS WHERE ID_ITEM=" & info.ID & ";"
                        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

                        If CType(row("BYTE_LOCATION"), ItemLocation) = ItemLocation.Shop Then
                            For Each itemdef As MirShopItemDef In lstShopDef
                                Dim item As ItemInfo = ItemInfoFromItemID(info.ID)
                                If itemdef.BYTE_TYPE = EvoLib.Protocol.mProtocol.ShopDefType.GridItem And itemdef.ItemInfo.INT_ID_ITEMBASE = item.Base.INT_ID_ITEMBASE Then

                                    If HasGold(conn, item.INT_REALCOST) Then

                                        sSql = "UPDATE " & mShopTableName & " SET BOOL_DELETED='TRUE' WHERE ID_ITEM=" & info.ID & ";"
                                        DB.GameDB.ExecuteNonQuery(sSql)

                                        sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Inventory & ", ID_CHARACTER=" & conn.CharacterID & " WHERE ID_ITEM=" & info.ID & ";"
                                        DB.GameDB.ExecuteNonQuery(sSql)

                                        sSql = "SELECT DISTINCT b.ID_ITEMBASE FROM " & mShopTableName & " a JOIN TBL_ITEMS b ON a.ID_ITEM = b.ID_ITEM WHERE a.BOOL_DELETED='False' AND b.ID_ITEMBASE=" & itemdef.ItemInfo.INT_ID_ITEMBASE & ";"
                                        row = DB.GameDB.ExecuteQueryFirstRecord(sSql)

                                        If row Is Nothing Then
                                            lstShopDef.Remove(itemdef)
                                            SendShopInfo(conn)
                                        ElseIf row.Count = 0 Then
                                            lstShopDef.Remove(itemdef)
                                            SendShopInfo(conn)
                                        End If

                                        LoadNewItem(conn, info.ID)

                                        TakeGold(conn, item.INT_REALCOST)

                                    Else

                                        Packets.SendSystemMessage(conn, "Not enough gold for that item!")

                                    End If


                                    Exit For

                                End If
                            Next

                        End If

                End Select

            End SyncLock

        End Sub

        Public Sub SendSellInfo(Conn As Connection)

            SyncLock objLock

                Dim pkt As Packet
                pkt.PacketType = GamePacketType.NPCShopBeginAllowList
                pkt.PacketOpCode = EvoLib.Protocol.mProtocol.PacketOpCode.Notify
                pkt.Username = Conn.Username

                Dim beginstruct As Protocol.ShopListInfo
                beginstruct.ID_NPC = mNPC_ID
                beginstruct.BYTE_TYPE = ShopListType.Sell

                Socket.SockServer.SendData(MakePacket(pkt, beginstruct, Conn.Crypto), Conn.Index)

                pkt.PacketType = GamePacketType.NPCShopAllow

                If lstAcceptsItemTypes.Count > 0 Then
                    For Each itemtype As ItemType In lstAcceptsItemTypes

                        Dim struct As ShopAllowList
                        struct.BYTE_TYPE = itemtype
                        Socket.SockServer.SendData(MakePacket(pkt, struct, Conn.Crypto), Conn)

                    Next
                End If

                pkt.PacketType = GamePacketType.NPCShopEndAllowList
                Socket.SockServer.SendData(MakePacket(pkt, , Conn.Crypto), Conn.Index)

            End SyncLock

        End Sub

        Public Sub SellItem(conn As Connection, info As ShopItemSellInfo)

            SyncLock objLock

                Dim sSql As String = "SELECT a.ID_ITEMBASE, a.INT_COUNT, b.STR_NAME FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE=b.ID_ITEMBASE WHERE ID_ITEM=" & info.ID & " AND ID_CHARACTER=" & conn.CharacterID & " AND BYTE_LOCATION=" & ItemLocation.Inventory & ";"
                Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

                If Not row Is Nothing Then
                    If row.Count > 0 Then
                        Dim base As ItemBaseInfo = ItemBaseInfoFromItemBaseID(row("ID_ITEMBASE"))
                        If lstAcceptsItemTypes.Contains(base.BYTE_TYPE) Then

                            If info.BYTE_DEFTYPE = ShopSellType.SellDoIt Then

                                If info.INT_COUNT > row("INT_COUNT") Then info.INT_COUNT = row("INT_COUNT")

                                RemoveItem(info.ID, conn)
                                Dim vals() As String = {info.ID.ToString, "'False'"}

                                Dim e As IEnumerator(Of MirShopItemDef) = lstShopDef.GetEnumerator()
                                Dim cols() As String = {"ID_ITEM", "BOOL_DELETED"}

                                Do Until Not e.MoveNext()
                                    If e.Current.ItemInfo.INT_ID_ITEMBASE = row("ID_ITEMBASE") Then

                                        If row("INT_COUNT") > 1 Then

                                            If row("INT_COUNT") > info.INT_COUNT Then

                                                Dim leftoverCount As Integer = row("INT_COUNT") - info.INT_COUNT
                                                sSql = "UPDATE TBL_ITEMS SET INT_COUNT=" & leftoverCount & ", BYTE_LOCATION=" & ItemLocation.Shop & " WHERE ID_ITEM=" & info.ID & ";"
                                                DB.GameDB.ExecuteNonQuery(sSql)
                                                LoadNewItem(conn, info.ID)
                                                If e.Current.BYTE_TYPE = ShopDefType.GridItem Then
                                                    For it As Integer = 1 To info.INT_COUNT
                                                        Dim id As Long = CreateNewItem(row("STR_NAME"), conn.CharacterID, 1, ItemLocation.Shop)
                                                        vals(0) = id.ToString
                                                        DB.GameDB.NewRecord(mShopTableName, cols, vals)
                                                    Next
                                                End If

                                            Else
                                                sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Shop & ", ID_CHARACTER=0 WHERE ID_ITEM=" & info.ID & ";"
                                                DB.GameDB.ExecuteNonQuery(sSql)

                                                If e.Current.BYTE_TYPE = ShopDefType.GridItem Then
                                                    For it As Integer = 1 To info.INT_COUNT
                                                        Dim id As Long = CreateNewItem(row("STR_NAME"), conn.CharacterID, 1, ItemLocation.Shop)
                                                        vals(0) = id.ToString
                                                        DB.GameDB.NewRecord(mShopTableName, cols, vals)
                                                    Next
                                                End If

                                            End If

                                        Else

                                            sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Shop & ", ID_CHARACTER=0 WHERE ID_ITEM=" & info.ID & ";"
                                            DB.GameDB.ExecuteNonQuery(sSql)

                                            If e.Current.BYTE_TYPE = ShopDefType.GridItem Then DB.GameDB.NewRecord(mShopTableName, cols, vals)

                                        End If



                                        AddGoldFromSellItem(conn, info)
                                        Exit Sub

                                    End If
                                Loop


                                If row("INT_COUNT") > 1 Then

                                    If row("INT_COUNT") > info.INT_COUNT Then

                                        Dim leftoverCount As Integer = row("INT_COUNT") - info.INT_COUNT
                                        sSql = "UPDATE TBL_ITEMS SET INT_COUNT=" & leftoverCount & ", BYTE_LOCATION=" & ItemLocation.Shop & " WHERE ID_ITEM=" & info.ID & ";"
                                        DB.GameDB.ExecuteNonQuery(sSql)
                                        LoadNewItem(conn, info.ID)
                                        For it As Integer = 1 To info.INT_COUNT
                                            Dim id As Long = CreateNewItem(row("STR_NAME"), conn.CharacterID, 1, ItemLocation.Shop)
                                            vals(0) = id.ToString
                                            DB.GameDB.NewRecord(mShopTableName, cols, vals)
                                        Next

                                    Else
                                        sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Shop & ", ID_CHARACTER=0 WHERE ID_ITEM=" & info.ID & ";"
                                        DB.GameDB.ExecuteNonQuery(sSql)

                                        For it As Integer = 1 To info.INT_COUNT
                                            Dim id As Long = CreateNewItem(row("STR_NAME"), conn.CharacterID, 1, ItemLocation.Shop)
                                            vals(0) = id.ToString
                                            DB.GameDB.NewRecord(mShopTableName, cols, vals)
                                        Next

                                    End If

                                Else

                                    sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Shop & ", ID_CHARACTER=0 WHERE ID_ITEM=" & info.ID & ";"
                                    DB.GameDB.ExecuteNonQuery(sSql)

                                    DB.GameDB.NewRecord(mShopTableName, cols, vals)

                                End If

                                Dim def As MirShopItemDef
                                def.BYTE_TYPE = EvoLib.Protocol.mProtocol.ShopDefType.GridItem
                                def.ID_ITEM = row("ID_ITEMBASE")
                                def.ItemInfo = base

                                lstShopDef.Add(def)

                                AddGoldFromSellItem(conn, info)

                            ElseIf info.BYTE_DEFTYPE = ShopSellType.SellGetPrice Then

                                Dim item_info As ItemInfo = ItemInfoFromItemID(info.ID)
                                Dim pkt As Packet
                                pkt.PacketType = GamePacketType.NPCShopSell
                                pkt.PacketOpCode = PacketOpCode.Answer
                                pkt.Username = conn.Username

                                Dim struct As NPCShopSellPrice
                                struct.ID = info.ID
                                struct.INT8_OFFER = CLng(item_info.INT_REALCOST * mShopSellRate)

                                Socket.SockServer.SendData(MakePacket(pkt, struct, conn.Crypto), conn)

                            ElseIf info.BYTE_DEFTYPE = ShopSellType.RepairGetCost Then

                                Dim item_info As ItemInfo = ItemInfoFromItemID(info.ID)
                                Dim pkt As Packet
                                pkt.PacketType = GamePacketType.NPCShopSell
                                pkt.PacketOpCode = PacketOpCode.Answer
                                pkt.Username = conn.Username

                                Dim struct As NPCShopSellPrice
                                struct.ID = info.ID
                                Dim maxdura As Long = CLng((item_info.Base.Stats.INT_MAX_DURABILITY + item_info.AddedStats.INT_MAX_DURABILITY) * 1000)
                                Dim cost As Long = CLng(item_info.Base.INT8_COST * ((maxdura - item_info.INT_DURABILITY) / maxdura))
                                struct.INT8_OFFER = cost

                                Socket.SockServer.SendData(MakePacket(pkt, struct, conn.Crypto), conn)

                            ElseIf info.BYTE_DEFTYPE = ShopSellType.RepairDoIt Then

                                Dim item_info As ItemInfo = ItemInfoFromItemID(info.ID)

                                Dim maxdura As Long = CLng((item_info.Base.Stats.INT_MAX_DURABILITY + item_info.AddedStats.INT_MAX_DURABILITY) * 1000)
                                Dim cost As Long = CLng(item_info.Base.INT8_COST * ((maxdura - item_info.INT_DURABILITY) / maxdura))

                                TakeGold(conn, cost)

                                RemoveItem(info.ID, conn)
                                sSql = "UPDATE TBL_ITEMS SET INT_DURABILITY=" & CLng((item_info.Base.Stats.INT_MAX_DURABILITY + item_info.AddedStats.INT_MAX_DURABILITY) * 1000) & " WHERE ID_ITEM=" & info.ID & " AND ID_CHARACTER=" & conn.CharacterID & ";"
                                DB.GameDB.ExecuteNonQuery(sSql)
                                System.Threading.Thread.Sleep(500)
                                LoadNewItem(conn, info.ID)


                            End If


                        End If
                    End If
                End If

            End SyncLock

        End Sub

        Private Sub AddGoldFromSellItem(conn As Connection, info As ShopItemSellInfo)

            If Not info.BYTE_DEFTYPE = ShopSellType.SellDoIt Then Exit Sub
            Dim item_info As ItemInfo = ItemInfoFromItemID(info.ID)
            RecieveGold(conn, CLng(item_info.INT_REALCOST * info.INT_COUNT))

        End Sub


        Public Sub SendRepairInfo(Conn As Connection)

            SyncLock objLock

                Dim pkt As Packet
                pkt.PacketType = GamePacketType.NPCShopBeginAllowList
                pkt.PacketOpCode = EvoLib.Protocol.mProtocol.PacketOpCode.Notify
                pkt.Username = Conn.Username

                Dim beginstruct As Protocol.ShopListInfo
                beginstruct.ID_NPC = mNPC_ID
                beginstruct.BYTE_TYPE = ShopListType.Repair

                Socket.SockServer.SendData(MakePacket(pkt, beginstruct, Conn.Crypto), Conn.Index)

                pkt.PacketType = GamePacketType.NPCShopAllow

                If lstAcceptsItemTypes.Count > 0 Then
                    For Each itemtype As ItemType In lstRepairsItemTypes

                        Dim struct As ShopAllowList
                        struct.BYTE_TYPE = itemtype
                        Socket.SockServer.SendData(MakePacket(pkt, struct, Conn.Crypto), Conn)

                    Next
                End If

                pkt.PacketType = GamePacketType.NPCShopEndAllowList
                Socket.SockServer.SendData(MakePacket(pkt, , Conn.Crypto), Conn.Index)

            End SyncLock

        End Sub

    End Class

    Friend Class mNPCList

        Public Structure MirMapNPC

            Dim NPCID As Int64
            Dim mName As String

            Dim mCMD As String

            Dim mShape As Integer

            Dim mX As Integer, mY As Integer

        End Structure

        Public lstNPCS As List(Of MirMapNPC)

        Public lstShops As SortedDictionary(Of Long, MirNPCShopDef)

        Private mParent As MirMap

        Private mNPCLock As New Object

        Public Sub New(ByRef parent As MirMap)

            mParent = parent

            lstNPCS = New List(Of MirMapNPC)
            lstShops = New SortedDictionary(Of Long, MirNPCShopDef)

        End Sub

        Public Sub Add(ID As Int64, name As String, cmd As String, shape As Integer, x As Integer, y As Integer)

            Dim tmp As New MirMapNPC

            tmp.NPCID = ID
            tmp.mName = name
            tmp.mCMD = cmd
            tmp.mShape = shape
            tmp.mX = x
            tmp.mY = y

            SyncLock mNPCLock

                lstNPCS.Add(tmp)

            End SyncLock

        End Sub

        Public Function Populate(npcdef As String) As Integer

            Dim count As Integer, failcount As Integer

            If Microsoft.VisualBasic.FileIO.FileSystem.FileExists(npcdef) Then

                Dim stream As System.IO.StreamReader = FileIO.FileSystem.OpenTextFileReader(npcdef)
                Dim line As String

                Do Until stream.EndOfStream

                    Try

                        line = stream.ReadLine()
                        TrimLineTabs(line)

                        If Left(line, 1) <> ";" Then

                            Dim id As Int64 = ReadNextValue(line)
                            Dim x As Integer = ReadNextValue(line)
                            Dim y As Integer = ReadNextValue(line)
                            Dim shape As Integer = ReadNextValue(line)
                            Dim name As String = ReadNextValue(line)
                            Dim cmd As String = ReadNextValue(line)

                            Add(id, name, cmd, shape, x, y)

                            failcount += LoadNPCShopDef(id)

                            count += 1

                        End If

                    Catch ex As Exception

                        Throw New Exception(ex.Message)
                        Output.AddLine("\B0\F3NP>\B8\F7Error in " & Right(npcdef, npcdef - (InStrRev(npcdef, "\") + 1)) & "! Near '" & line & "'\F0")
                        failcount += 1

                    End Try
                Loop

            End If

            Output.AddLine("\B0\F3NP>\F0\B8 Loaded " & count & " NPCs! (\F7" & failcount & " failed\F0)")
            Return failcount

        End Function

        Public Function LoadNPCShopDef(id_npc As Long) As Integer

            Dim file As String = Globals.sServerPath & "ShopDef\" & mParent.file & "\" & id_npc & ".txt"
            Dim failcount As Integer

            If System.IO.File.Exists(file) Then
                Dim ShopDef As New MirNPCShopDef(id_npc)
                failcount = ShopDef.LoadFromFile(file)

                lstShops.Add(id_npc, ShopDef)
            End If

            Return failcount

        End Function

        Public Sub LoadShopBuy(npc_id As Long, conn As Connection)

            SyncLock mNPCLock

                If lstShops.ContainsKey(npc_id) Then

                    lstShops(npc_id).SendShopInfo(conn)

                Else
                    Dim pkt As Packet
                    pkt.PacketType = GamePacketType.NPCCall
                    pkt.PacketOpCode = EvoLib.Protocol.mProtocol.PacketOpCode.NegAcknowledge
                    pkt.Username = conn.Username

                    Socket.SockServer.SendData(MakePacket(pkt, , conn.Crypto), conn)
                End If

            End SyncLock

        End Sub

    End Class

End Namespace
